package com.lzy.files.controller;

import com.lzy.api.controller.files.FileUploaderControllerApi;
import com.lzy.exception.GraceException;
import com.lzy.files.resource.FileResource;
import com.lzy.files.service.UploaderService;
import com.lzy.grace.result.GraceJSONResult;
import com.lzy.grace.result.ResponseStatusEnum;
import com.lzy.pojo.bo.NewAdminBO;
import com.lzy.utils.FileUtils;
import com.lzy.utils.extend.AliImageReviewUtils;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.model.Filters;
import com.mongodb.gridfs.GridFS;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@RestController
public class FileUploaderController implements FileUploaderControllerApi {

    final static Logger logger = LoggerFactory.getLogger(FileUploaderController.class);

    @Autowired
    private UploaderService uploaderService;

    @Autowired
    private FileResource fileResource;

    @Autowired
    private AliImageReviewUtils aliImageReviewUtils;

    @Autowired
    private GridFSBucket gridFSBucket;

    @Override
    public GraceJSONResult uploadFace(String userId, MultipartFile file) throws Exception {

        // 1. 判断是否登录
        if(StringUtils.isBlank(userId)){
            return GraceJSONResult.errorCustom(ResponseStatusEnum.UN_LOGIN);
        }

        String path = null;
        // 2. 判断文件是否为空
        if(file != null){
            // 获得文件上传的名称
            String fileName = file.getOriginalFilename();
            // 判断文件名不能为空
            if(StringUtils.isNotBlank(fileName)){
                String fileNameArr[] = fileName.split("\\.");
                // 获得后缀
                String suffix = fileNameArr[fileNameArr.length - 1];
                // 判断后缀
                if(! suffix.equalsIgnoreCase("png") &&
                   ! suffix.equalsIgnoreCase(("jpg")) &&
                   ! suffix.equalsIgnoreCase("jpeg")
                  ){
                    return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_FORMATTER_FAILD);
                }
                 // fastDFS方式上传
//                path = uploaderService.UploadFdfs(file,suffix);
                // OSS方式上传
                  path = uploaderService.UploadOSS(file,userId,suffix);
            }
        }else{
            return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_UPLOAD_NULL_ERROR);
        }

        logger.info("path = " + path);

        String finalPath = "";
        if(StringUtils.isNotBlank(path)){
            finalPath = fileResource.getOssHost() + path;

        }else{
            return GraceJSONResult.errorCustom(ResponseStatusEnum.FILE_UPLOAD_FAILD);
        }
        return GraceJSONResult.ok(doAliImageReview(finalPath));
    }

    @Override
    public GraceJSONResult uploadSomeFiles(String userId,
                                           MultipartFile[] files,
                                           HttpServletRequest request,
                                           HttpServletResponse response) throws Exception {
        // 用于存储多个图片的list，返回到前端
        List<String> imagesUrlList = new ArrayList<>();
        // 多文件上传必须不为空并且该文件数组长度大于0
        if (files != null && files.length > 0) {
            for (MultipartFile file : files) {
                String path = "";
                // 开始文件上传，判断不能为空
                if (file != null) {
                    // 获得文件上传的名称
                    String fileName = file.getOriginalFilename();
                    // 判断文件名不能为空
                    if(StringUtils.isNotBlank(fileName)){
                        String fileNameArr[] = fileName.split("\\.");
                        // 获得后缀
                        String suffix = fileNameArr[fileNameArr.length - 1];
                        // 判断后缀
                        if(! suffix.equalsIgnoreCase("png") &&
                                ! suffix.equalsIgnoreCase(("jpg")) &&
                                ! suffix.equalsIgnoreCase("jpeg")
                        ){
                            continue;
                        }
                        // OSS方式上传
                        path = uploaderService.UploadOSS(file,userId,suffix);
                        }
                    logger.info("path = " + path);
                    String finalPath = "";
                    if(StringUtils.isNotBlank(path)){
                        finalPath = fileResource.getOssHost() + path;
                        // FIXME:在放入到imagelist之前要对图片进行一次审核
                        imagesUrlList.add(doAliImageReview(finalPath));
                    }else{
                        continue;
                    }
                }
            }
        }
            return GraceJSONResult.ok(imagesUrlList);
    }

    @Override
    public GraceJSONResult uploadToGridFS(NewAdminBO newAdminBO) throws Exception {

        // 获得图片的base64字符串
        String file64 = newAdminBO.getImg64();

        // 将base64字符串转换为byte数组
        byte[] bytes = new BASE64Decoder().decodeBuffer(file64.trim());

        // 转换为输入流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

        // 上传到gridfs中
        ObjectId fileId = gridFSBucket.uploadFromStream(newAdminBO.getUsername() + ".png",byteArrayInputStream);

        // 获得文件在gridfs中的主键
        String fileIdStr = fileId.toString();

        return GraceJSONResult.ok(fileIdStr);
    }

    @Override
    public void readInGridFS(String faceId,
                                        HttpServletRequest request,
                                        HttpServletResponse response) throws Exception {

        // 1. 判断参数是否正确
        if(StringUtils.isBlank(faceId) || faceId.equalsIgnoreCase("null")){
             GraceException.display(ResponseStatusEnum.FILE_NOT_EXIST_ERROR);
        }

        // 2. 从gridfs中提取调用
        File adminFace = readGridFSByFaceId(faceId);

        // 3. 把人脸图片输出在浏览器
        FileUtils.downloadFileByStream(response,adminFace);
    }

    @Override
    public GraceJSONResult readFace64InGridFs(String faceId,
                                              HttpServletRequest request,
                                              HttpServletResponse response) throws Exception {
        // 1. 获得gridfs中人脸文件
        File myfile = readGridFSByFaceId(faceId);

        // 2. 转换人脸数据位base64
        String base64Face = FileUtils.fileToBase64(myfile);

        return GraceJSONResult.ok(base64Face);
    }

    public static final String FAILED_IMAGE_URL = "https://lzy-news-dev.oss-cn-beijing.aliyuncs.com/images/%E5%AE%A1%E6%A0%B8%E5%A4%B1%E8%B4%A5.jpg";
    private String doAliImageReview(String pendingImageUrl) throws Exception {
        boolean result = false;
        try {
            result = aliImageReviewUtils.reviewImage(pendingImageUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if(!result){
            return FAILED_IMAGE_URL;
        }
        return pendingImageUrl;
    }



    /**
     *
     * 通过faceid从gridfs中获取file文件
     */
    private File readGridFSByFaceId(String faceId) throws FileNotFoundException {
        GridFSFindIterable gridFSFiles =
                gridFSBucket.find(Filters.eq("_id",new ObjectId(faceId)));
        GridFSFile gridFS = gridFSFiles.first();

        if(gridFS == null){
            GraceException.display(ResponseStatusEnum.FILE_NOT_EXIST_ERROR);
        }

        String fileName = gridFS.getFilename();
        System.out.println(fileName);

        // 获取文件流，保存文件到本地或者服务器的临时目录
        File fileTmp = new File("/workspace/temp_face");
        if(!fileTmp.exists()){
            fileTmp.mkdirs();
        }

        File myFile = new File("/workspace/temp_face/" + fileName);

        // 创建文件的输出流
        OutputStream os = new FileOutputStream(myFile);
        gridFSBucket.downloadToStream(new ObjectId(faceId),os);

        return myFile;
    }
}
